package boterkoeklaag;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.nio.*;
/*
 * FIELDS:     | DST | SRC | LENGTH | TYPE
 * BITS:          8     8      31      1
 */

public class Boterkoeklaag extends Thread {

	private Socket socket;
	private InputStream in;
	private OutputStream out;
//	private Speculaaslaag speculaas;

	public Boterkoeklaag(Socket socket) {
//		this.speculaas = speculaas;
		this.socket = socket;
		try {
			this.in = socket.getInputStream();
			this.out = socket.getOutputStream();
		} catch (IOException e) {
			close();
		}
		start();
	}
	
	public void run() {
		while(true) {
			byte[] header = null;
			try {
				header = new byte[6];
				int i = in.read(header,0,6);
				if (i == -1) {
					System.err.println("Fail in InputStream");
					System.exit(-1);
				}
			} catch (IOException e) {
				System.err.println("Fail in InputStream");
				System.exit(-1);
			}
			byte dst = header[0];
			byte src = header[1];
			int length = ByteBuffer.wrap(header, 2, 4).getInt();
			int type = length % 2;
			length = length >> 1;
			byte[] message = new byte[length];
			try {
				int i = in.read(message, 0, length);
				if (i == -1) {
					System.err.println("Fail in InputStream");
					System.exit(-1);
				}
			} catch (IOException e) {
				System.err.println("Fail in InputStream");
				System.exit(-1);
			}
			System.out.println(dst + ", " + src + ", " + message.toString());
//			speculaas.handleMessage(dst,src,message);
		}
	}

	private List<Byte> packMessage(byte dst, byte src, int type, List<Byte> msg) {
		List<Byte> result = new ArrayList<Byte>();
		result.add(dst);
		result.add(src);
		int i = msg.size();
		byte b = (byte) (i << 1);
		b += (byte) type;
		result.add(b);
		result.addAll(msg);
		return result;
	}

	public void sendMessage(byte dst, byte src, int type, List<Byte> msg) {
		try {
			List<Byte> byteStream = packMessage(dst, src, type, msg);
			for(byte b: byteStream) {
				out.write(b);
			}
			out.flush();
		} catch (IOException e) {
			close();
		}
	}

	private void close() {
		try {
			in.close();
			out.close();
			socket.close();
		} catch (IOException e) {
			System.err.println("Fail in close()");
		}
	}
	
	public static void main(String[] args) {
		Socket sock = null;
		boolean server = false;
		try {
			sock = new Socket("130.89.238.225", 5555);

		} catch (IOException e) {
			server = true;
		}
		if (server) {
			ServerSocket s;
			try {
				s = new ServerSocket(5555);
				sock = s.accept();
			} catch (IOException e) {
				System.err.println("Big error");
				System.exit(-1);
			}
		}
		Boterkoeklaag boterkoek = new Boterkoeklaag(sock);
	}
}
